﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FluentFTP;
using Flurl.Http;
using Newtonsoft.Json.Linq;
using Pay.Core;
using Pay.DTO;
using Pay.DTO.hfnative;
using Pay.DTO.hfpay;
using Pay.IService;
using Pay.TO;

namespace Pay.Service {
    /// <summary>
    /// HF-银联
    /// </summary>
    public class HfPayService : ServiceBase2, IPayService, IDisposable {
        private ISettingService _iSettingService;
        private IMerchantService _iMerchantService;
        private IChargeService _iChargeService;
        private IRefundService _iRefundService;
        private ITransferService _iTransferService;
        private IProfitDayService _iProfitDayService;
        private IBillService _iBillService;
        private IPayHtmlService _iPayHtmlService;
        private IPayNotifyService _iPayNotifyService;
        private IRegionService _iRegionService;
        private HfSign _hfSign;

        public HfPayService(IUnitOfWork iUnitOfWork, ISettingService iSettingService,
                        IMerchantService iMerchantService, IChargeService iChargeService, IRefundService iRefundService,
                        ITransferService iTransferService, IProfitDayService iProfitDayService, IBillService iBillService,
                        IPayHtmlService iPayHtmlService, IPayNotifyService iPayNotifyService, IRegionService iRegionService) : base(iUnitOfWork) {
            _iSettingService = iSettingService;
            _iMerchantService = iMerchantService;
            _iChargeService = iChargeService;
            _iRefundService = iRefundService;
            _iTransferService = iTransferService;
            _iProfitDayService = iProfitDayService;
            _iBillService = iBillService;
            _iPayHtmlService = iPayHtmlService;
            _iPayNotifyService = iPayNotifyService;
            _iRegionService = iRegionService;
            _hfSign = new HfSign();
        }
        #region 扫码的
        /// <summary>
        /// HF扫码支付请求通道封装
        /// </summary>
        /// <returns>The pay gateway.</returns>
        /// <param name="model">Model.</param>
        /// <typeparam name="T">The 1st type parameter.</typeparam>
        public async Task<native_result> NativePay(native_model model) {
            var setting = _iSettingService.Get();
            var user = _iMerchantService.Get(model.bind_no);
            if (model.pay_code.Contains("WXPAY") && user.setting.hf_set.open_wx != AuthStatusEnum.Auth)
                return await ApiResultToJson.JsonAsync<native_result>("微信支付商户进件待审核，请求失败");
            //var merchant = _iMerchantService.Get(obj["merchant_no"].ToString());
            var amount = (decimal.Parse(model.tran_amount) / 100).ToString("0.00");
            //把商户请求转为通道请求消息
            hf_pay_native_model pay_model = null;
            var id = Guid.NewGuid().ToString("N");
            var notifyUrl = setting.site.api_url + "/hf_native_notify/" + id + "?settle_type=" + model.settle_type;
            //string front_notify = model.front_notify;
            if (model.pay_code == "WXPAY_JS") {
                pay_model = new hf_pay_wxPub_model {
                    amount = amount, body = model.body, callbackUrl = model.front_notify, channel = "wxPub", notifyUrl = notifyUrl,
                    outTradeNo = model.order_no, subAppId = model.appid, subOpenId = model.openid, subject = model.subject
                };
            } else if (model.pay_code == "WXPAY_APP") {
                pay_model = new hf_pay_wxAPP_model {
                    amount = amount, body = model.body, channel = "wxApp", notifyUrl = notifyUrl,
                    outTradeNo = model.order_no, mobileAppId = model.appid, subject = model.subject,
                };
            } else if (model.pay_code == "WXPAY_QR" || model.pay_code == "ALIPAY_QR" || model.pay_code == "JDPAY_QR" || model.pay_code == "ALIPAY_JS") {
                string channel = "";
                if (model.pay_code == "WXPAY_QR") channel = "wxPubQR";
                else if (model.pay_code == "ALIPAY_QR" || model.pay_code == "ALIPAY_JS") channel = "alipayQR";
                else if (model.pay_code == "JDPAY_QR") channel = "jdQR";
                //else if (pay_code == "ALIPAY_JS") channel = "alipayApp";
                pay_model = new hf_pay_native_model {
                    amount = amount, body = model.body, channel = channel, notifyUrl = notifyUrl,
                    outTradeNo = model.order_no, subject = model.subject
                };
            } else if (model.pay_code == "WXPAY_MICRO" || model.pay_code == "ALIPAY_MICRO") {
                string channel = "";
                if (model.pay_code == "WXPAY_MICRO") channel = "wxMicro";
                else if (model.pay_code == "ALIPAY_MICRO") channel = "alipayMicro";
                pay_model = new hf_wx_alipay_micro_model {
                    amount = amount, body = model.body, channel = channel, notifyUrl = notifyUrl,
                    outTradeNo = model.order_no, subject = model.subject, authCode = model.auth_code
                };
            } else if (model.pay_code == "UNIONPAY_QR" || model.pay_code == "QQ_QR") {
                string channel = "";
                if (model.pay_code == "UNIONPAY_QR") channel = "unionpayQR";
                else if (model.pay_code == "QQ_QR") channel = "qqwalletQR";
                pay_model = new hf_pay_unionpay_qq_model {
                    amount = amount, body = model.body, callbackUrl = model.front_notify, channel = channel, notifyUrl = notifyUrl,
                    outTradeNo = model.order_no, subject = model.subject
                };
            }
            if (model.settle_type == "T0") {
                pay_model.mchId = _hfSign.t0_native_mchid;
                pay_model.subMchId = user.setting.hf_set.t0_native_mchid;
                pay_model.sign = _hfSign.Sign(pay_model, _hfSign.t0_native_key);
            } else {
                pay_model.mchId = _hfSign.t1_native_mchid;
                pay_model.subMchId = user.setting.hf_set.t1_native_mchid;
                pay_model.sign = _hfSign.Sign(pay_model, _hfSign.t1_native_key);
            }
            //调用通道执行并处理返回，请通道响应消息封装为平台响应商户消息
            var pay_rep = await _hfSign.PostNative<pay_native_result>(pay_model);
            if (pay_rep != null) {
                if (pay_rep.returnCode == "0") {
                    if (pay_rep.resultCode == "0") {
                        //创建订单
                        model.transaction_no = pay_rep.channelOrderNo;
                        var charge = _iChargeService.AddByNativePay(model);
                        charge.pay_info.transaction_no = pay_rep.channelOrderNo;
                        //将HTML保存到mongodb
                        var ok = _iPayHtmlService.Save(new pay_html_dto { id = id, html = "扫码等", merchant_no = model.merchant_no, order_no = model.order_no, charge = charge.ToJson() });
                        if (ok) {
                            var data = new native_result {
                                code_url = pay_rep.codeUrl, order_no = pay_rep.outTradeNo, pay_info = pay_rep.payCode, transaction_no = pay_rep.channelOrderNo
                            };
                            return ApiResultToJson.Json(data);
                        }
                        return await ApiResultToJson.JsonAsync<native_result>("支付请求失败");
                    } else {
                        return await ApiResultToJson.JsonAsync<native_result>(pay_rep.errCodeDes);
                    }
                } else {
                    return await ApiResultToJson.JsonAsync<native_result>(pay_rep.returnMsg);
                }
            }
            return await ApiResultToJson.JsonAsync<native_result>("支付请求失败");
        }
        #endregion

        #region 支付异步通知
        /// <summary>
        /// 回调支付通知，商户返回OK，不再回调了，流程是先调用ChargeService的NotifyOrder，
        /// 返回值判断是调用哪个通道，再调用本方法，最后调用ChargeService的Update
        /// </summary>
        /// <returns>The notify.</returns>
        /// <param name="order_no">Order.</param>
        public async Task<string> Notify(string merchant_no, string order_no) {
            string result = string.Empty;
            var order = _iChargeService.Get(merchant_no, order_no);
            if (order == null) return "OK";
            try {
                //防止HF－T0的交易不确认时，再1分钟内不做查询
                //if (order.pay_info.pay_channel == PayChannel.HF && order.order_time.AddMinutes(1) > DateTime.Now) return "交易进行中";
                //if (order.status == ChargeStatus.UnConfirm) return "OK";
                var setting = order.merchant.setting;
                var data = new pay_notity {
                    tran_amount = ((int)(order.order_amount * 100)).ToString(), order_no = order.order_no, transaction_no = order.pay_info.transaction_no,
                    pay_time = order.pay_info.pay_time.HasValue ? order.pay_info.pay_time.Value : order.order_time,
                    status = (order.status == ChargeStatus.Finish ? 1 : 2)
                };
                //失败的要再查询通道判断是否真失败,处理掉单
                if (order.status == ChargeStatus.Fail || order.status == ChargeStatus.UnConfirm && !string.IsNullOrEmpty(order.pay_info.transaction_no)) {
                    if (order.pay_info.pay_type == PayType.Quick) {
                        var hfData = new HFBankData<head_base, hf_quick_pay_query>();
                        hfData.head.merNo = setting.hf_set.quick_mchid;
                        hfData.head.tranCode = "2003";
                        hfData.body = new hf_quick_pay_query { origTranId = order.pay_info.transaction_no, tranType = "0" };
                        hfData.head.signature = _hfSign.Sign(hfData);
                        var hfResult = await _hfSign.PayGateway<hf_quick_pay_query_reuslt>(hfData);
                        var respCode = hfResult.body.respCode;
                        if (respCode == "0000" && hfResult.body.origRespCode.Substring(0, 1) == "0") {
                            data.status = 1;
                            DateTime pay_time = DateTime.Now;
                            if (!string.IsNullOrEmpty(hfResult.body.transDate))
                                pay_time = hfResult.body.transDate.ToDateTime();
                            _iChargeService.FailOrUnConfirmToSuceess(merchant_no, order.order_no, pay_time);
                        }
                    } else if (order.pay_info.pay_type == PayType.Gateway) {
                        var hfData = new HFBankData<head_base, hf_gateway_pay_query>();
                        hfData.head.merNo = setting.hf_set.quick_mchid;
                        hfData.head.tranCode = "2012";
                        hfData.body = new hf_gateway_pay_query { origTranId = order.pay_info.transaction_no, tranDate = order.order_time.ToString("yyyyMMdd") };
                        hfData.head.signature = _hfSign.Sign(hfData);
                        var hfResult = await _hfSign.PayGateway<hf_gateway_pay_query_reuslt>(hfData);
                        var respCode = hfResult.body.respCode.Substring(0, 1);
                        if (respCode == "0" && hfResult.body.origRespCode == "0") {
                            data.status = 1;
                            _iChargeService.FailOrUnConfirmToSuceess(merchant_no, order.order_no, order.order_time);
                        }
                    } else {
                        //扫码
                        var pay_model = new hf_native_query { outTradeNo = order.order_no, queryType = "1" };
                        if (order.pay_info.settle_type == "T0") {
                            pay_model.mchId = _hfSign.t0_native_mchid;
                            pay_model.subMchId = order.binder.setting.hf_set.t0_native_mchid;
                            pay_model.sign = _hfSign.Sign(pay_model, _hfSign.t0_native_key);
                        } else {
                            pay_model.mchId = _hfSign.t1_native_mchid;
                            pay_model.subMchId = order.binder.setting.hf_set.t1_native_mchid;
                            pay_model.sign = _hfSign.Sign(pay_model, _hfSign.t1_native_key);
                        }
                        var pay_rep = await _hfSign.PostNative<hf_native_query_result>(pay_model);
                        if (pay_rep != null) {
                            if (pay_rep.returnCode == "0") {
                                if (pay_rep.resultCode == "0") {
                                    if (pay_rep.status == "02") {
                                        data.status = 1;
                                        _iChargeService.FailOrUnConfirmToSuceess(merchant_no, order.order_no, pay_rep.transTime.ToDateTime(), pay_rep.outChannelNo);
                                    }
                                } else {
                                    order.fail = pay_rep.errCodeDes;
                                }
                            } else {
                                order.fail = pay_rep.returnMsg;
                            }
                        }
                    }
                }
                data.result_msg = (data.status == 1 ? "支付成功" : order.fail);
                if (string.IsNullOrEmpty(order.notify)) return "OK";
                var notify_result = await order.notify.PostJsonAsync(ApiResultToJson.Json(data)).ReceiveJson<ResultMessage<string>>();
                result = notify_result.data;
                var log = IocHelper.Get<ILogHelper>("info");
                log.Info(order.order_no + ":" + notify_result.ToJson());
            } catch (Exception ex) {
                var log = IocHelper.Get<ILogHelper>("info");
                log.Error("订单通道查询异常:" + order.order_no);
                log.Error(ex.Message);
            }
            return result;
        }

        /// <summary>
        /// 代付通知
        /// </summary>
        /// <returns>The transfer.</returns>
        /// <param name="order_no">Order.</param>
        public async Task<string> NotifyTransfer(string merchant_no, string order_no) {
            string result = string.Empty;
            var transfer = _iTransferService.Get(merchant_no, order_no);
            if (transfer == null) return "OK";
            try {
                //var setting = transfer.merchant.setting;
                var data = new transfer_result {
                    order_no = transfer.order_no, transaction_no = transfer.pay_info.transaction_no,
                    pay_time = transfer.pay_info.pay_time.HasValue ? transfer.pay_info.pay_time.Value : transfer.apply_time
                };
                if (transfer.status == TransferStatus.UnConfirm) data.status = 2;
                else if (transfer.status == TransferStatus.Fail) data.status = 3;
                else if (transfer.status == TransferStatus.Finish) data.status = 1;
                //不确定的要再查询通道判断是否有结果了,处理掉单
                string msg = transfer.fail;
                if (transfer.status == TransferStatus.UnConfirm) {
                    //HF快捷代付查询
                    if (transfer.pay_info.pay_channel == PayChannel.HF && transfer.pay_info.pay_code == "UNIONPAY") {
                        var hfData = new HFBankData<head_base, hf_transfer_query>();
                        hfData.head.merNo = _hfSign.merNo;
                        hfData.head.tranCode = "1201";
                        hfData.body = new hf_transfer_query { origTranId = data.transaction_no, origTranTime = data.pay_time.Value.ToString("yyyyMMddHHmmss") };
                        hfData.head.signature = _hfSign.Sign(hfData);
                        var hfResult = await _hfSign.PayGateway<hf_transfer_reuslt>(hfData);
                        if (hfResult != null) {
                            if (hfResult.body.respCode == "0000") {
                                if (hfResult.body.origTranState == "0") {
                                    //代付成功
                                    data.status = 1;
                                    _iTransferService.TransferSuccess(new platform_transfer {
                                        pay_time = data.pay_time, transaction_no = data.transaction_no,
                                        order_no = data.order_no, status = TransferStatus.Finish, merchant_no = merchant_no
                                    });
                                }
                            } else if (hfResult.body.respCode == "1101") {
                                //返回0000表示查询成功；返回1101表示查无此交易，如果代付交易发完后隔2分钟查仍是1101，可确认为原交易失败；
                                //其他都是查询失败，需要再次查询。可能有退汇的数据，详情参考退汇查询接口。
                                msg = !string.IsNullOrEmpty(hfResult.body.origRespMsg) ? hfResult.body.origRespMsg : "提现失败";
                                data.status = 2;
                            }
                        }
                    } else {
                        //HF扫码TO代付查询
                        //var pay_model = new hf_native_query { outTradeNo = transfer.order_no, queryType = "1" };
                        //pay_model.mchId = _hfSign.t0_native_mchid;
                        //pay_model.subMchId = transfer.binder.setting.hf_set.t0_native_mchid;
                        //pay_model.sign = _hfSign.Sign(pay_model, _hfSign.t0_native_key);
                        //var pay_rep = await _hfSign.PostNative<hf_native_query_result>(pay_model);
                        //if (pay_rep != null) {
                        //	if (pay_rep.returnCode == "0") {
                        //		if (pay_rep.resultCode == "0") {
                        //			if (pay_rep.status == "02") {
                        //				data.status = 1;
                        //				_iTransferService.UnConfirmFailToSuceess(new platform_transfer {
                        //					pay_time = data.pay_time, transaction_no = data.transaction_no,
                        //					order_no = data.order_no, status = TransferStatus.Finish
                        //				});
                        //			} else if (pay_rep.status == "09") {
                        //				msg = !string.IsNullOrEmpty(pay_rep.errCodeDes) ? pay_rep.errCodeDes : "提现失败";
                        //				data.status = 3;
                        //			} else {
                        //				msg = !string.IsNullOrEmpty(pay_rep.errCodeDes) ? pay_rep.errCodeDes : "不确定";
                        //				data.status = 2;
                        //			}
                        //		} else {
                        //			return pay_rep.errCodeDes;
                        //		}
                        //	} else {
                        //		return pay_rep.returnMsg;
                        //	}
                        //}
                    }
                }
                data.result_msg = data.status == 1 ? "提现成功" : msg;
                if (!string.IsNullOrEmpty(transfer.notify)) {
                    var notify_result = await transfer.notify.PostJsonAsync(ApiResultToJson.Json(data)).ReceiveJson<ResultMessage<string>>();
                    result = notify_result.data;
                    var log = IocHelper.Get<ILogHelper>("info");
                    log.Info(transfer.order_no + ":" + notify_result.ToJson());
                } else
                    result = "OK";
            } catch (Exception ex) {
                var log = IocHelper.Get<ILogHelper>("info");
                log.Error("代付通知异常:" + transfer.order_no);
                log.Error(ex.Message);
            }
            return result;
        }
        #endregion

        #region T1额度/四要素
        /// <summary>
        /// 查询代付T1额度
        /// </summary>
        /// <returns>The quota.</returns>
        /// <param name="merchant_no"></param>
        /// <param name="busiType">0：对公 1：对私</param>
        public async Task<quota_result> Quota(string merchant_no, string busiType) {
            //var merchant = _iMerchantService.Get(merchant_no);
            //var setting = merchant.setting;
            var result = new quota_result();
            if (busiType == "3") {
                var pay_model = new pay_native_balance();
                pay_model.mchId = _hfSign.t0_native_mchid;
                pay_model.sign = _hfSign.Sign(pay_model, _hfSign.t0_native_key);
                var hfResult = await _hfSign.PostNative3<pay_native_balance_result>(pay_model);
                if (hfResult.returnCode == "0" && hfResult.resultCode == "0") {
                    result.total = hfResult.freezeBalance;
                    result.balance = hfResult.balance;
                }
            } else {
                var hfData = new HFBankData<head_base, hf_quota>();
                hfData.head.merNo = _hfSign.merNo;
                hfData.head.tranCode = "2103";
                hfData.body = new hf_quota { busiType = busiType };
                hfData.head.signature = _hfSign.Sign(hfData);
                var hfResult = await _hfSign.PayGateway<hf_quota_result>(hfData);
                if (hfResult != null && hfResult.body.respCode.Substring(0, 1) == "0") {
                    result.total = hfResult.body.totalSum;
                    result.balance = hfResult.body.balance;
                }
            }
            return ApiResultToJson.Json("查询完成", result);
        }

        /// <summary>
        /// 四要素认证
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<certify_verify_result> CertifyVerify(certify_verify model) {
            var hfData = new HFBankData<head_base, hf_certify_verify>();
            hfData.head.merNo = _hfSign.merNo;
            hfData.head.tranCode = "1601";
            hfData.body = new hf_certify_verify {
                acctName = model.account_name, acctNo = model.account_no, accType = "1", certNo = model.id_card,
                certType = "00", verifyType = model.verify_type
            };
            hfData.head.signature = _hfSign.Sign2(hfData);
            var hfResult = await _hfSign.PayGateway<body_base>(hfData);
            if (hfResult != null) {
                //开头为0 - 成功；；1 - 不确定；其他失败
                var respCode = hfResult.body.respCode.Substring(0, 1);
                if (respCode == "0") {
                    model.status = CertifyStatus.Auth;
                    _iMerchantService.CertifyVerify(model, hfResult.body.respMsg);
                    return ApiResultToJson.Json("认证成功", new certify_verify_result { status = AuthStatusEnum.Auth });
                } else if (respCode == "1") {
                    model.status = CertifyStatus.UnConfirm;
                    _iMerchantService.CertifyVerify(model, hfResult.body.respMsg);
                    return ApiResultToJson.Json("待确认认证", new certify_verify_result { status = AuthStatusEnum.Wait });
                } else {
                    model.status = CertifyStatus.Fail;
                    _iMerchantService.CertifyVerify(model, hfResult.body.respMsg);
                    return ApiResultToJson.Json("等待认证", new certify_verify_result { status = AuthStatusEnum.Fail });
                }
            } else {
                return ApiResultToJson.Json("认证失败", new certify_verify_result { status = AuthStatusEnum.Wait });
            }
        }
        #endregion

        #region 快捷支付
        private string SetMerchantBankCode(string bank_code) {
            var banks = new Dictionary<string, string>();
            banks.Add("ABC", "103100000026");
            banks.Add("BCM", "301290000007");
            banks.Add("BOC", "104100000004");
            banks.Add("CCB", "105100000017");
            banks.Add("CEB", "303100000006");
            banks.Add("CGB", "306331003281");
            banks.Add("CIB", "309391000011");
            banks.Add("CITIC", "302100011000");
            banks.Add("CMB", "308584000013");
            banks.Add("CMBC", "305100000013");
            banks.Add("HXB", "304100040000");
            banks.Add("ICBC", "102100099996");
            banks.Add("PSBC", "403100000004");
            banks.Add("SPDB", "310290000013");
            banks.Add("PAB", "307584007998");
            return banks[bank_code];
        }
        /// <summary>
        /// 快捷支付鉴权
        /// </summary>
        /// <returns>The receive.</returns>
        /// <param name="model">Model.</param>
        public async Task<quick_pay_result> QuickPay(quick_pay_model model) {
            charge_dto charge = _iChargeService.AddByQuickPay(model);
            DateTime pay_time = DateTime.Now;
            var merchant = _iMerchantService.Get(model.merchant_no);
            var setting = merchant.setting;
            var hfData = new HFBankData<head_base, hf_quick_pay>();
            string transaction_no = hfData.head.tranId;
            hfData.head.merNo = setting.hf_set.quick_mchid;
            hfData.head.tranCode = "2001";
            hfData.body = model.ToDtoObject<hf_quick_pay>();
            hfData.body.rcvAcctName = charge.rcv_account_name;
            hfData.body.rcvAcctNo = charge.rcv_account_no;
            hfData.body.rcvBankName = charge.rcv_bank_name;
            hfData.body.rcvBankCode = charge.rcv_bank_code;
            hfData.body.buyerIp = StringHelper.GetHostAddress();
            if (charge != null && charge.is_out) {
                hfData.body.settleAmt = ((int)(charge.amount * 100)).ToString();
                hfData.body.rcvBankCode = SetMerchantBankCode(charge.rcv_bank_code);
            }
            hfData.head.signature = _hfSign.Sign(hfData);
            var hfResult = await _hfSign.PayGateway<hf_quick_pay_result>(hfData);
            if (hfResult != null && !string.IsNullOrEmpty(hfResult.body.respCode)) {
                if (hfResult.body.respCode.Substring(0, 1) == "0") {
                    charge.pay_info.transaction_no = transaction_no;
                    charge.protocol_no = hfResult.body.protocolNo;
                    var id = Guid.NewGuid().ToString("N");
                    //将HTML保存到mongodb
                    var ok = _iPayHtmlService.Save(new pay_html_dto { id = id, html = "HF支付", merchant_no = model.merchant_no, order_no = model.order_no, charge = charge.ToJson() });
                    if (ok) {
                        return ApiResultToJson.Json("鉴权成功，待确认支付", new quick_pay_result {
                            order_no = model.order_no, protocol_no = hfResult.body.protocolNo, request_url = hfResult.body.requestUrl,
                            pay_time = pay_time, transaction_no = transaction_no, status = 3
                        });
                    }
                } else {
                    string fail = hfResult.body.respMsg;
                    return ApiResultToJson.Json(fail, new quick_pay_result {
                        order_no = model.order_no, protocol_no = "",
                        pay_time = pay_time, transaction_no = transaction_no, status = 2
                    });
                }
            }
            return ApiResultToJson.Json<quick_pay_result>("异常支付");
        }

        /// <summary>
        /// 快捷支付鉴权成功后发短信
        /// </summary>
        /// <returns>The pay resms.</returns>
        /// <param name="model">model.</param>
        public async Task<ApiResultMessage> QuickPaySendsms(quick_sendsms_model model) {
            var payHtml = _iPayHtmlService.Get(model.merchant_no, model.order_no);
            var charge = payHtml.charge.ToObject<charge_dto>();
            var merchant = _iMerchantService.Get(model.merchant_no);
            var setting = merchant.setting;
            var hfData = new HFBankData<head_base, object>();
            hfData.head.merNo = setting.hf_set.quick_mchid;
            hfData.head.tranCode = "2007";
            hfData.body = new { origTranId = charge.pay_info.transaction_no, protocolNo = charge.protocol_no };
            hfData.head.signature = _hfSign.Sign(hfData);
            var hfResult = await _hfSign.PayGateway<body_base>(hfData);
            if (hfResult != null) {
                if (hfResult.body.respCode.Substring(0, 1) == "0") {
                    return new ApiResultMessage("短信发送");
                } else {
                    string fail = hfResult.body.respMsg;
                    return new ApiResultMessage(1001, fail);
                }
            }
            return new ApiResultMessage(1002, "短信发送异常");
        }

        /// <summary>
        /// 确认短信验证码－快捷支付
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<quick_pay_result> QuickPay(quick_sms_model model) {
            var payHtml = _iPayHtmlService.Get(model.merchant_no, model.order_no);
            var order = payHtml.charge.ToObject<charge_dto>();
            DateTime pay_time = DateTime.Now;
            var merchant = _iMerchantService.Get(model.merchant_no);
            var setting = merchant.setting;
            var hfData = new HFBankData<head_base, object>();
            hfData.head.merNo = setting.hf_set.quick_mchid;
            hfData.head.tranCode = "2002";
            hfData.body = new { origTranId = order.pay_info.transaction_no, smsVerCode = model.sms_code };
            hfData.head.signature = _hfSign.Sign(hfData);
            var hfResult = await _hfSign.PayGateway<hf_quick_pay_result>(hfData);
            if (hfResult != null) {
                var result = hfResult.body.respCode.Substring(0, 1);
                if (result == "0") {
                    _iChargeService.PaySuceess(payHtml, order.pay_info.transaction_no, pay_time);
                    _iPayNotifyService.Save(new pay_notify_dto { merchant_no = order.merchant_no, order_no = order.order_no, pay_channel = order.pay_info.pay_channel, type = 1, status = (int)order.status, create_time = DateTime.Now });
                    return ApiResultToJson.Json("支付成功", new quick_pay_result {
                        order_no = order.order_no, protocol_no = order.protocol_no,
                        pay_time = pay_time, transaction_no = order.pay_info.transaction_no, status = 1
                    });
                } else if (result == "1") {
                    string fail = !string.IsNullOrEmpty(hfResult.body.respMsg) ? hfResult.body.respMsg : "支付中";
                    //更新payhtml
                    order.fail = fail;
                    payHtml.charge = order.ToJson();
                    _iPayHtmlService.Update(payHtml);
                    return ApiResultToJson.Json("支付中", new quick_pay_result {
                        order_no = order.order_no, protocol_no = order.protocol_no,
                        pay_time = pay_time, transaction_no = order.pay_info.transaction_no, status = 3
                    });
                } else {
                    string fail = !string.IsNullOrEmpty(hfResult.body.respMsg) ? hfResult.body.respMsg : "支付失败";
                    //更新payhtml
                    order.fail = fail;
                    payHtml.charge = order.ToJson();
                    _iPayHtmlService.Update(payHtml);
                    return ApiResultToJson.Json(fail, new quick_pay_result {
                        order_no = order.order_no, protocol_no = "",
                        pay_time = pay_time, transaction_no = order.pay_info.transaction_no, status = 2
                    });
                }
            } else {
                return ApiResultToJson.Json<quick_pay_result>("异常支付");
            }
        }

        /// <summary>
        /// 快捷支付或扫码、sdk支付查询
        /// </summary>
        /// <returns>The pay query.</returns>
        /// <param name="model">Model.</param>
        public async Task<pay_notity> QuickPayQuery(refund_model_query model) {
            charge_dto order = null; pay_html_dto obj = null;
            if (!string.IsNullOrEmpty(model.order_no)) order = _iChargeService.Get(model.merchant_no, model.order_no);
            else order = _iChargeService.GetByTran(model.transaction_no);
            if (order == null) {
                obj = _iPayHtmlService.Get(model.merchant_no, model.order_no);
                if (obj != null) {
                    order = obj.charge.ToObject<charge_dto>();
                }
            }
            if (order.pay_info.pay_type == PayType.Quick)
                return await quickPayQuery(order, obj);
            else if (order.pay_info.pay_type == PayType.JSPAY || order.pay_info.pay_type == PayType.Native || order.pay_info.pay_type == PayType.SDK)
                return await nativePayQuery(order, obj);
            return ApiResultToJson.Json<pay_notity>("查询异常");
        }

        /// <summary>
        /// 快捷支付查询
        /// </summary>
        /// <returns>The pay query.</returns>
        /// <param name="order">Model.</param>
        private async Task<pay_notity> quickPayQuery(charge_dto order, pay_html_dto obj = null) {
            var data = new pay_notity { status = 2, order_no = order.order_no };
            if (obj != null) {
                var merchant = _iMerchantService.Get(order.merchant_id);
                var hfData = new HFBankData<head_base, hf_quick_pay_query>();
                hfData.head.merNo = merchant.setting.hf_set.quick_mchid;
                hfData.head.tranCode = "2003";
                hfData.body = new hf_quick_pay_query { origTranId = order.pay_info.transaction_no, tranType = "0" };
                hfData.head.signature = _hfSign.Sign(hfData);
                var hfResult = await _hfSign.PayGateway<hf_quick_pay_query_reuslt>(hfData);
                if (hfResult != null && hfResult.body.respCode == "0000") {
                    var respCode = hfResult.body.origRespCode.Substring(0, 1);
                    if (respCode == "0") {
                        data.status = 1; data.pay_time = obj.create_time; data.result_msg = "支付成功"; data.tran_amount = ((int)order.amount * 100).ToString();
                        var result = _iChargeService.PaySuceess(obj, order.pay_info.transaction_no, data.pay_time);
                        if (result > 0) {
                            var notifyResult = await Notify(order.merchant_no, order.order_no);
                            _iPayHtmlService.Remove(obj.id);
                        }
                    } else if (respCode == "1") {
                        data.result_code = 1001; data.result_msg = !string.IsNullOrEmpty(hfResult.body.origRespMsg) ? hfResult.body.origRespMsg : order.fail;
                        data.pay_time = obj.create_time; data.tran_amount = ((int)order.amount * 100).ToString();
                    } else {
                        data.result_code = 1001; data.result_msg = !string.IsNullOrEmpty(hfResult.body.origRespMsg) ? hfResult.body.origRespMsg : order.fail;
                        data.pay_time = obj.create_time; data.tran_amount = ((int)order.amount * 100).ToString();
                    }
                }
            } else {
                data.status = order.status == ChargeStatus.Finish ? 1 : 2; data.pay_time = order.order_time; data.transaction_no = order.pay_info.transaction_no;
                data.result_msg = order.status == ChargeStatus.Finish ? "支付成功" : "支付失败"; data.tran_amount = ((int)order.amount * 100).ToString();
                if (order.status != ChargeStatus.Finish) data.result_code = 1001;
            }
            return data;
        }

        /// <summary>
        /// 扫码支付查询
        /// </summary>
        /// <returns>The pay query.</returns>
        public async Task<pay_notity> nativePayQuery(charge_dto order, pay_html_dto obj = null) {
            var data = new pay_notity { status = 2, order_no = order.order_no };
            if (obj != null) {
                var binder = _iMerchantService.Get(order.bind_id ?? order.merchant_id);
                var pay_model = new hf_native_query { outTradeNo = order.order_no, queryType = "1" };
                if (order.pay_info.settle_type == "T0") {
                    pay_model.mchId = _hfSign.t0_native_mchid;
                    pay_model.subMchId = binder.setting.hf_set.t0_native_mchid;
                    pay_model.sign = _hfSign.Sign(pay_model, _hfSign.t0_native_key);
                } else {
                    pay_model.mchId = _hfSign.t1_native_mchid;
                    pay_model.subMchId = binder.setting.hf_set.t1_native_mchid;
                    pay_model.sign = _hfSign.Sign(pay_model, _hfSign.t1_native_key);
                }
                var pay_rep = await _hfSign.PostNative<hf_native_query_result>(pay_model);
                if (pay_rep != null) {
                    if (pay_rep.returnCode == "0") {
                        if (pay_rep.resultCode == "0") {
                            if (pay_rep.status == "02") {
                                data.status = 1; data.pay_time = obj.create_time; data.result_msg = "支付成功"; data.tran_amount = ((int)order.amount * 100).ToString();
                                var result = _iChargeService.PaySuceess(obj, order.pay_info.transaction_no, data.pay_time);
                                if (result > 0) {
                                    var notifyResult = await Notify(order.merchant_no, order.order_no);
                                    _iPayHtmlService.Remove(obj.id);
                                }
                            } else {
                                data.result_code = 1001; data.result_msg = "支付失败";
                                data.pay_time = obj.create_time; data.tran_amount = ((int)order.amount * 100).ToString();
                            }
                        } else {
                            data.result_code = 1001; data.result_msg = pay_rep.errCodeDes;
                            data.pay_time = obj.create_time; data.tran_amount = ((int)order.amount * 100).ToString();
                        }
                    } else {
                        data.result_code = 1001; data.result_msg = pay_rep.returnMsg;
                        data.pay_time = obj.create_time; data.tran_amount = ((int)order.amount * 100).ToString();
                    }
                } else {
                    data.result_code = 1001; data.result_msg = "支付失败";
                }
            } else {
                data.status = order.status == ChargeStatus.Finish ? 1 : 2; data.pay_time = order.order_time; data.transaction_no = order.pay_info.transaction_no;
                data.result_msg = order.status == ChargeStatus.Finish ? "支付成功" : "支付失败"; data.tran_amount = ((int)order.amount * 100).ToString();
                if (order.status != ChargeStatus.Finish) data.result_code = 1001;
            }
            return data;
        }

        /// <summary>
        /// 快捷支付退款
        /// </summary>
        /// <returns>The pay refund.</returns>
        /// <param name="model">Model.</param>
        public async Task<refund_result> QuickPayRefund(refund_model model) {
            var result = _iRefundService.ApplyRefund(model);
            DateTime pay_time = DateTime.Now;
            if (result > 0) {
                var merchant = _iMerchantService.Get(model.merchant_no);
                var setting = merchant.setting;
                var hfData = new HFBankData<head_base, hf_quick_refund>();
                string transaction_no = hfData.head.tranId;
                hfData.head.merNo = setting.hf_set.quick_mchid;
                hfData.head.tranCode = "2004";
                hfData.body.tranAmt = model.tran_amount;
                hfData.body.origTranId = model.transaction_no;
                hfData.head.signature = _hfSign.Sign(hfData);
                var hfResult = await _hfSign.PayGateway<body_base>(hfData);
                if (hfResult != null) {
                    string msg = "退款成功";
                    RefundStatus status;
                    var respCode = hfResult.body.respCode.Substring(0, 1);//开头为0-成功；1-不确定；其他失败
                    if (respCode == "0") {
                        status = RefundStatus.Finish;
                        _iRefundService.PlatformRefundAmount(model.order_no, transaction_no, pay_time, status);
                    } else if (respCode == "1") {
                        msg = "退款进行中";
                        status = RefundStatus.Walt;
                        _iRefundService.PlatformRefundAmount(model.order_no, transaction_no, pay_time, status);
                    } else {
                        msg = !string.IsNullOrEmpty(hfResult.body.respMsg) ? hfResult.body.respMsg : "退款失败";
                        status = RefundStatus.Fail;
                        _iRefundService.PlatformRefundAmount(model.order_no, transaction_no, pay_time, status, msg);
                    }
                    return ApiResultToJson.Json(msg, new refund_result {
                        order_no = model.order_no, transaction_no = transaction_no,
                        pay_time = pay_time, tran_amount = model.tran_amount, status = status
                    });
                }
            }
            return ApiResultToJson.Json<refund_result>("异常退款");
        }

        /// <summary>
        /// 快捷支付退款查询,并将退款中的单处理为完成
        /// </summary>
        /// <returns>The pay refund.</returns>
        /// <param name="model">Model.</param>
        public async Task<refund_result> QuickPayRefundQuery(refund_model_query model) {
            refund_dto order = null;
            if (!string.IsNullOrEmpty(model.order_no)) order = _iRefundService.Get(model.order_no);
            else order = _iRefundService.GetByTran(model.transaction_no);
            DateTime pay_time = order.pay_info.pay_time.HasValue ? order.pay_info.pay_time.Value : order.apply_time;
            var transaction_no = order.pay_info.transaction_no;
            var merchant = _iMerchantService.Get(model.merchant_no);
            var setting = merchant.setting;
            var hfData = new HFBankData<head_base, hf_quick_pay_query>();
            hfData.head.merNo = setting.hf_set.quick_mchid;
            hfData.head.tranCode = "2003";
            hfData.body = new hf_quick_pay_query { origTranId = transaction_no, tranType = "1" };
            hfData.head.signature = _hfSign.Sign(hfData);
            var hfResult = await _hfSign.PayGateway<hf_quick_pay_query_reuslt>(hfData);
            if (hfResult != null) {
                string msg = "退款成功";
                RefundStatus status;
                var respCode = hfResult.body.respCode;
                if (respCode == "0000") {
                    var state = hfResult.body.origRespCode.Substring(0, 1);
                    if (state == "0") {
                        status = RefundStatus.Finish;
                        if (order.status == RefundStatus.Walt || order.status == RefundStatus.Fail) {
                            _iRefundService.PlatformRefundAmount(order.order_no, transaction_no, pay_time, status);
                        }
                    } else if (state == "1") {
                        msg = "退款进行中";
                        status = RefundStatus.Walt;
                        _iRefundService.PlatformRefundAmount(model.order_no, transaction_no, pay_time, status);
                    } else {
                        msg = !string.IsNullOrEmpty(hfResult.body.respMsg) ? hfResult.body.respMsg : "退款失败";
                        status = RefundStatus.Fail;
                        _iRefundService.PlatformRefundAmount(model.order_no, transaction_no, pay_time, status, msg);
                    }
                    return ApiResultToJson.Json(msg, new refund_result {
                        order_no = model.order_no, transaction_no = transaction_no,
                        pay_time = pay_time, tran_amount = ((int)(order.amount * 100)).ToString(), status = status
                    });
                }
            }
            return ApiResultToJson.Json<refund_result>("异常退款查询");
        }
        #endregion

        #region 网关支付
        /// <summary>
        /// 网关支付银行
        /// </summary>
        /// <returns>The pay bank.</returns>
        public List<type_setting> GatewayPayBank() {
            var banks = new List<type_setting>();
            banks.Add(new type_setting { value = "BOC", text = "中国银行" });
            banks.Add(new type_setting { value = "ABC", text = "中国农业银行" });
            banks.Add(new type_setting { value = "ICBC", text = "中国工商银行" });
            banks.Add(new type_setting { value = "CCB", text = "中国建设银行" });
            banks.Add(new type_setting { value = "COMM", text = "交通银行" });
            banks.Add(new type_setting { value = "PSBC", text = "中国邮政储蓄银行" });
            banks.Add(new type_setting { value = "CMB", text = "招商银行" });
            banks.Add(new type_setting { value = "CMBC", text = "中国民生银行" });
            banks.Add(new type_setting { value = "CITIC", text = "中信银行" });
            banks.Add(new type_setting { value = "CEB", text = "中国光大银行" });
            banks.Add(new type_setting { value = "HXB", text = "华夏银行" });
            banks.Add(new type_setting { value = "GDB", text = "广发银行" });
            banks.Add(new type_setting { value = "CIB", text = "兴业银行" });
            banks.Add(new type_setting { value = "SPDB", text = "上海浦东发展银行" });
            banks.Add(new type_setting { value = "SPAB", text = "平安银行" });
            banks.Add(new type_setting { value = "SHB", text = "上海银行" });
            banks.Add(new type_setting { value = "BJB", text = "北京银行" });
            banks.Add(new type_setting { value = "HZCB", text = "杭州银行" });
            return banks;
        }

        /// <summary>
        /// 发起网关支付
        /// </summary>
        /// <returns>The receive.</returns>
        /// <param name="model">Model.</param>
        public async Task<gateway_pay_result> GatewayPay(gateway_pay_model model) {
            var merchant = _iMerchantService.Get(model.merchant_no);
            var setting = merchant.setting;
            var hfData = new HFBankData<head_base, hf_gateway_pay>();
            model.transaction_no = hfData.head.tranId;
            model.bank_name = GatewayPayBank().First(c => c.value == model.bank_code).text;
            hfData.head.merNo = setting.hf_set.quick_mchid;
            hfData.head.tranCode = "2011";
            hfData.body = new hf_gateway_pay { bankCode = model.bank_code, tranAmt = model.tran_amount };
            hfData.head.signature = _hfSign.Sign(hfData);
            var hfResult = await _hfSign.PayGateway<hf_gateway_pay_result>(hfData);
            if (hfResult != null && !string.IsNullOrEmpty(hfResult.body.requestUrl)) {
                _iChargeService.AddByGatewayPay(model);
                return ApiResultToJson.Json("网关支付提交成功", new gateway_pay_result {
                    order_no = model.order_no, request_url = hfResult.body.requestUrl
                });
            }
            return ApiResultToJson.Json<gateway_pay_result>("网关支付提交失败");
        }

        /// <summary>
        /// 网关支付查询
        /// </summary>
        /// <returns>The pay query.</returns>
        /// <param name="model">Model.</param>
        public async Task<pay_notity> GatewayPayQuery(refund_model_query model) {
            charge_dto order = null;
            if (!string.IsNullOrEmpty(model.order_no)) order = _iChargeService.Get(model.merchant_no, model.order_no);
            else order = _iChargeService.GetByTran(model.transaction_no);
            var data = new pay_notity {
                tran_amount = ((int)(order.order_amount * 100)).ToString(), order_no = order.order_no, transaction_no = order.pay_info.transaction_no,
                pay_time = order.pay_info.pay_time.HasValue ? order.pay_info.pay_time.Value : order.order_time
            };
            string msg = "";
            var setting = order.merchant.setting;
            var hfData = new HFBankData<head_base, hf_gateway_pay_query>();
            hfData.head.merNo = setting.hf_set.quick_mchid;
            hfData.head.tranCode = "2012";
            hfData.body = new hf_gateway_pay_query { origTranId = order.pay_info.transaction_no, tranDate = data.pay_time.ToString("yyyyMMdd") };
            hfData.head.signature = _hfSign.Sign(hfData);
            var hfResult = await _hfSign.PayGateway<hf_gateway_pay_query_reuslt>(hfData);
            if (hfResult != null) {
                //查询成功，origRespCode返回;被查询交易的状态；开头为0-成功；1-未知；2失败；3交易已撤销；4-交易已退款
                if (hfResult.body.respCode == "0000" && hfResult.body.origRespCode == "0") {
                    data.status = 1;
                    msg = "支付成功";
                    if (order.status != ChargeStatus.Finish)
                        _iChargeService.FailOrUnConfirmToSuceess(model.merchant_no, order.order_no, data.pay_time);
                } else {
                    data.status = 2;
                    msg = !string.IsNullOrEmpty(hfResult.body.origRespMsg) ? hfResult.body.origRespMsg : order.fail;
                }
                return ApiResultToJson.Json(msg, data);
            }
            return ApiResultToJson.Json<pay_notity>("网关支付查询异常");
        }

        /// <summary>
        /// 网关支付退款
        /// </summary>
        /// <returns>The pay refund.</returns>
        /// <param name="model">Model.</param>
        public async Task<refund_result> GatewayPayRefund(refund_model model) {
            var result = _iRefundService.ApplyRefund(model);
            DateTime pay_time = DateTime.Now;
            if (result > 0) {
                charge_dto order = null;
                if (!string.IsNullOrEmpty(model.orig_order_no)) order = _iChargeService.Get(model.merchant_no, model.orig_order_no);
                else order = _iChargeService.GetByTran(model.transaction_no);
                var hfData = new HFBankData<head_base, hf_gateway_refund>();
                string transaction_no = hfData.head.tranId;
                var setting = order.merchant.setting;
                hfData.head.merNo = setting.hf_set.quick_mchid;
                hfData.head.tranCode = "2014";
                hfData.body.tranAmt = model.tran_amount;
                hfData.body.origTranId = order.pay_info.transaction_no;
                hfData.body.origAmt = ((int)(order.pay_amount * 100)).ToString();
                hfData.body.tranDate = order.pay_info.pay_time.Value.ToString("yyyyMMdd");
                hfData.head.signature = _hfSign.Sign(hfData);
                var hfResult = await _hfSign.PayGateway<body_base>(hfData);
                if (hfResult != null) {
                    string msg = "退款成功";
                    RefundStatus status;
                    var respCode = hfResult.body.respCode.Substring(0, 1);//:0开头成功，1开头处理中，2开头失败
                    if (respCode == "0") {
                        status = RefundStatus.Finish;
                        _iRefundService.PlatformRefundAmount(model.order_no, transaction_no, pay_time, status);
                    } else if (respCode == "1") {
                        msg = "退款进行中";
                        status = RefundStatus.Walt;
                        _iRefundService.PlatformRefundAmount(model.order_no, transaction_no, pay_time, status);
                    } else {
                        msg = !string.IsNullOrEmpty(hfResult.body.respMsg) ? hfResult.body.respMsg : "退款失败";
                        status = RefundStatus.Fail;
                        _iRefundService.PlatformRefundAmount(model.order_no, transaction_no, pay_time, status, msg);
                    }
                    return ApiResultToJson.Json(msg, new refund_result {
                        order_no = model.order_no, transaction_no = transaction_no,
                        pay_time = pay_time, tran_amount = model.tran_amount, status = status
                    });
                }
            }
            return ApiResultToJson.Json<refund_result>("异常退款");
        }

        /// <summary>
        /// 网关支付退款查询,并将退款中的单处理为完成
        /// </summary>
        /// <returns>The pay refund.</returns>
        /// <param name="model">Model.</param>
        public async Task<refund_result> GatewayRefundQuery(refund_model_query model) {
            refund_dto order = null;
            if (!string.IsNullOrEmpty(model.order_no)) order = _iRefundService.Get(model.order_no);
            else order = _iRefundService.GetByTran(model.transaction_no);
            DateTime pay_time = order.pay_info.pay_time.HasValue ? order.pay_info.pay_time.Value : order.apply_time;
            var transaction_no = order.pay_info.transaction_no;
            var merchant = _iMerchantService.Get(model.merchant_no);
            var setting = merchant.setting;
            var hfData = new HFBankData<head_base, hf_gateway_refund_query>();
            hfData.head.merNo = setting.hf_set.quick_mchid;
            hfData.head.tranCode = "2015";
            hfData.body = new hf_gateway_refund_query { refundTranId = transaction_no };
            hfData.head.signature = _hfSign.Sign(hfData);
            var hfResult = await _hfSign.PayGateway<body_base>(hfData);
            if (hfResult != null) {
                string msg = "退款成功";
                RefundStatus status;
                var respCode = hfResult.body.respCode.Substring(0, 1);//0开头成功，1开头处理中，2开头失败
                if (respCode == "0") {
                    status = RefundStatus.Finish;
                    if (order.status == RefundStatus.Walt || order.status == RefundStatus.Fail) {
                        _iRefundService.PlatformRefundAmount(order.order_no, transaction_no, pay_time, status);
                    }
                } else if (respCode == "1") {
                    msg = "退款进行中";
                    status = RefundStatus.Walt;
                    _iRefundService.PlatformRefundAmount(model.order_no, transaction_no, pay_time, status);
                } else {
                    msg = !string.IsNullOrEmpty(hfResult.body.respMsg) ? hfResult.body.respMsg : "退款失败";
                    status = RefundStatus.Fail;
                    _iRefundService.PlatformRefundAmount(model.order_no, transaction_no, pay_time, status, msg);
                }
                return ApiResultToJson.Json(msg, new refund_result {
                    order_no = model.order_no, transaction_no = transaction_no,
                    pay_time = pay_time, tran_amount = ((int)(order.amount * 100)).ToString(), status = status
                });
            }
            return ApiResultToJson.Json<refund_result>("异常退款查询");
        }
        #endregion

        #region 代付,T+0转账
        /// <summary>
        /// 单笔代付
        /// </summary>
        /// <returns>The transfer.</returns>
        /// <param name="model">Model.</param>
        public async Task<transfer_result> Transfer(apply_transfer model) {
            //var site = _iSettingService.Get().site;
            if (model.settle_type == "T0") {
                //如果不是快捷的，就是扫码或APP
                if (model.pay_code != "UNIONPAY") {
                    return await NativeTransfer(model);
                }
                var result = _iTransferService.ApplyTransfer(model);
                var binder = _iMerchantService.Get(model.bind_no);
                var auth_info = binder.setting.auth_info;
                var hfData = new HFBankData<head_base, hf_transfer>();
                var transaction_no = hfData.head.tranId;
                model.transaction_no = transaction_no;
                hfData.head.merNo = _hfSign.merNo;//setting.hf_set.quick_mchid;
                hfData.head.tranCode = "2201";
                hfData.body = new hf_transfer {
                    acctType = "1", busiType = "1", certNo = auth_info.id_card, certType = "00", chkFlag = "1",
                    currency = "CNY", rcvAcctName = auth_info.account_name, rcvAcctNo = auth_info.account_no,
                    rcvBankName = auth_info.bank_name, rcvBankSettleNo = DtoHelper.RandCode(12), remark = "余额提现",
                    tranAmt = model.tran_amount
                };
                hfData.head.signature = _hfSign.Sign(hfData);
                var hfResult = await _hfSign.PayGateway<body_base>(hfData);
                int status = 0;//结算状态：1－到账成功，2－不确定，3－失败
                string msg = "";
                DateTime pay_time = hfData.head.tranTime.ToDateTime();
                if (hfResult != null) {
                    //如果返回码是1开头是未知，需要发起查询接口查询最终结果；开头为0-成功；1-不确定；其他失败
                    var respCode = hfResult.body.respCode.Substring(0, 1);
                    TransferStatus transferStatus = TransferStatus.None;
                    if (respCode == "0") {
                        //代付成功，生成账单和账
                        status = 1;
                        msg = "提现成功";
                        transferStatus = TransferStatus.Finish;
                        _iTransferService.TransferSuccess(new platform_transfer {
                            pay_time = pay_time, transaction_no = transaction_no, status = transferStatus,
                            order_no = model.order_no, merchant_no = model.merchant_no
                        });
                    } else if (respCode == "1") {
                        //不确定，生成账单和账
                        status = 2;
                        msg = hfResult.body.respMsg;
                        transferStatus = TransferStatus.UnConfirm;
                        _iTransferService.TransferFail(new platform_transfer {
                            pay_time = pay_time, transaction_no = transaction_no, status = transferStatus,
                            order_no = model.order_no, merchant_no = model.merchant_no
                        });
                    } else {
                        //代付失败，不生成账单和账
                        status = 3;
                        msg = !string.IsNullOrEmpty(hfResult.body.respMsg) ? hfResult.body.respMsg : "提现失败";
                        transferStatus = TransferStatus.Fail;
                        _iTransferService.TransferFail(new platform_transfer {
                            pay_time = pay_time, transaction_no = transaction_no, status = transferStatus,
                            order_no = model.order_no, fail = msg, merchant_no = model.merchant_no
                        });
                    }
                } else {
                    //代付失败，不生成账单和账
                    status = 3;
                    msg = "代付请求失败";
                    _iTransferService.TransferFail(new platform_transfer {
                        pay_time = pay_time, transaction_no = transaction_no, status = TransferStatus.Fail,
                        order_no = model.order_no, fail = msg, merchant_no = model.merchant_no
                    });
                }
                return ApiResultToJson.Json(msg, new transfer_result {
                    order_no = model.order_no, transaction_no = transaction_no,
                    pay_time = pay_time, status = status
                });
            } else {
                //次日代付，生成账单和账
                _iTransferService.ApplyTransfer(model);
                return ApiResultToJson.Json("提现进行中", new transfer_result {
                    order_no = model.order_no, transaction_no = "",
                    pay_time = null, status = 4
                });
            }
        }

        /// <summary>
        /// 扫码、APP支付的D0提现
        /// </summary>
        /// <returns>The transfer.</returns>
        /// <param name="model">Model.</param>
        private async Task<transfer_result> NativeTransfer(apply_transfer model) {
            _iTransferService.ApplyTransfer(model);
            var user = _iMerchantService.Get(model.bind_no);
            var pay_model = new pay_native_transfer { amount = decimal.Parse(model.tran_amount) / 100, description = "货款提现", outTradeNo = model.order_no };
            pay_model.mchId = _hfSign.t0_native_mchid;
            pay_model.subMchId = user.setting.hf_set.t0_native_mchid;
            pay_model.sign = _hfSign.Sign2(pay_model, _hfSign.t0_native_key);
            int status = 0;//结算状态：1－到账成功，2－不确定，3－失败
            string msg = "";
            string transaction_no = model.order_no;
            DateTime pay_time = DateTime.Now;
            var pay_rep = await _hfSign.PostNative2<pay_native_transfer_result>(pay_model);
            if (pay_rep != null) {
                if (pay_rep.returnCode == "0" && pay_rep.resultCode == "0") {
                    TransferStatus transferStatus = TransferStatus.None;
                    if (pay_rep.status == "0") {
                        //代付成功，生成账单和账
                        status = 1;
                        msg = "提现成功";
                        transferStatus = TransferStatus.Finish;
                        _iTransferService.TransferSuccess(new platform_transfer {
                            pay_time = pay_time, transaction_no = transaction_no, status = transferStatus,
                            order_no = model.order_no, merchant_no = model.merchant_no
                        });
                    } else if (pay_rep.status == "2") {
                        //不确定，生成账单和账
                        status = 2;
                        msg = pay_rep.errCodeDes;
                        transferStatus = TransferStatus.UnConfirm;
                        _iTransferService.TransferFail(new platform_transfer {
                            pay_time = pay_time, transaction_no = transaction_no, status = transferStatus,
                            order_no = model.order_no, merchant_no = model.merchant_no
                        });
                    } else {
                        //代付失败，不生成账单和账
                        status = 3;
                        msg = !string.IsNullOrEmpty(pay_rep.errCodeDes) ? pay_rep.errCodeDes : "提现失败";
                        transferStatus = TransferStatus.Fail;
                        _iTransferService.TransferFail(new platform_transfer {
                            pay_time = pay_time, transaction_no = transaction_no, status = transferStatus,
                            order_no = model.order_no, fail = msg, merchant_no = model.merchant_no
                        });
                    }
                }
            } else {
                //代付失败，不生成账单和账
                status = 3;
                msg = "代付请求失败";
                _iTransferService.TransferFail(new platform_transfer {
                    pay_time = pay_time, transaction_no = transaction_no, status = TransferStatus.Fail,
                    order_no = model.order_no, fail = msg, merchant_no = model.merchant_no
                });
            }
            return ApiResultToJson.Json(msg, new transfer_result {
                order_no = model.order_no, transaction_no = transaction_no,
                pay_time = pay_time, status = status
            });
        }

        /// <summary>
        /// 再原来提现单上重新代付
        /// </summary>
        /// <returns>The transfer.</returns>
        /// <param name="id">Identifier.</param>
        public async Task<transfer_result> ReTransfer(long id) {
            var transfer = _iTransferService.Get(id);
            var merchant = _iMerchantService.Get(transfer.bind_id);
            var auth_info = merchant.setting.auth_info;
            var hfData = new HFBankData<head_base, hf_transfer>();
            var transaction_no = hfData.head.tranId;
            hfData.head.merNo = _hfSign.merNo;
            hfData.head.tranCode = "2201";
            hfData.body = new hf_transfer {
                acctType = "1", busiType = "1", certNo = auth_info.id_card, certType = "00", chkFlag = "1",
                currency = "CNY", rcvAcctName = auth_info.account_name, rcvAcctNo = auth_info.account_no,
                rcvBankName = auth_info.bank_name, rcvBankSettleNo = DtoHelper.RandCode(12), remark = "余额提现",
                tranAmt = ((int)(transfer.transfer_amount * 100)).ToString()
            };
            hfData.head.signature = _hfSign.Sign(hfData);
            var hfResult = await _hfSign.PayGateway<body_base>(hfData);
            int status = 0;//结算状态：1－到账成功，2－不确定，3－失败
            string msg = "";
            DateTime pay_time = hfData.head.tranTime.ToDateTime();
            if (hfResult != null) {
                //如果返回码是1开头是未知，需要发起查询接口查询最终结果；开头为0-成功；1-不确定；其他失败
                var respCode = hfResult.body.respCode.Substring(0, 1);
                TransferStatus transferStatus = TransferStatus.None;
                if (respCode == "0") {
                    //代付成功，生成账单和账
                    status = 1;
                    msg = "提现成功";
                    transferStatus = TransferStatus.Finish;
                    _iTransferService.ReTransfer(new re_transfer {
                        pay_time = pay_time, transaction_no = transaction_no, status = transferStatus,
                        order_no = transfer.order_no, auth_info = auth_info, merchant_no = transfer.merchant.merchant_no
                    });
                } else if (respCode == "1") {
                    //不确定，生成账单和账
                    status = 2;
                    msg = hfResult.body.respMsg;
                    transferStatus = TransferStatus.UnConfirm;
                    _iTransferService.ReTransfer(new re_transfer {
                        pay_time = pay_time, transaction_no = transaction_no, status = transferStatus,
                        order_no = transfer.order_no, auth_info = auth_info, merchant_no = transfer.merchant.merchant_no
                    });
                } else {
                    //代付失败，不生成账单和账
                    status = 3;
                    msg = !string.IsNullOrEmpty(hfResult.body.respMsg) ? hfResult.body.respMsg : "提现失败";
                    transferStatus = TransferStatus.Fail;
                    _iTransferService.ReTransfer(new re_transfer {
                        pay_time = pay_time, transaction_no = transaction_no, status = transferStatus,
                        order_no = transfer.order_no, fail = msg, auth_info = auth_info, merchant_no = transfer.merchant.merchant_no
                    });
                }
            } else {
                //代付失败，不生成账单和账
                status = 3;
                msg = "代付请求失败";
                _iTransferService.TransferFail(new platform_transfer {
                    pay_time = pay_time, transaction_no = transaction_no, status = TransferStatus.Fail,
                    order_no = transfer.order_no, fail = msg, merchant_no = transfer.merchant.merchant_no
                });
            }
            return ApiResultToJson.Json(msg, new transfer_result {
                order_no = transfer.order_no, transaction_no = transaction_no,
                pay_time = pay_time, status = status
            });
        }

        /// <summary>
        /// 代付批处理:生成代付文件，将批号写入提现表，生成代付文件记录，并上传FTP，FTP成功调用代付通知，FTP失败提示手动上传，并去文件记录管理手动代付通知。
        /// </summary>
        /// <returns>The transfer.</returns>
        /// <param name="model">Model.</param>
        public async Task<batch_transfer_result> Transfer(batch_transfer model) {
            var hfData = new HFBankData<head_base, hf_transfer_notify>();
            string batchNo = DateTime.Now.ToString("yyMMdd") + hfData.head.platCode + DtoHelper.RandCode(6);
            string batchFileName = batchNo + "_" + _hfSign.merNo + ".txt";
            model.batch_file = batchFileName;
            model.batch_no = batchNo;
            var dt = DateTime.Now;

            //生成代付文件
            string total_row = string.Format("{0}|{1}|{2}|{3}|{4}|{5}|{6}|{7}|", dt.ToString("yyyyMMdd"), dt.ToString("hhmmss"), "厦门商付宝", hfData.head.merNo,
                                             batchNo, model.orders.Count, model.orders.Select(c => int.Parse(c.tran_amount)).Sum(), 1);
            List<string> rows = new List<string>();
            int i = 1000;
            foreach (var item in model.orders) {
                item.transaction_no = batchNo + i.ToString();
                rows.Add(string.Format("{0}|{1}|{2}|{3}|{4}|{5}|{6}", item.transaction_no, DtoHelper.RandCode(12),
                                       item.bank_name, item.account_no, item.account_name, item.tran_amount, "余额转账"));
                i++;
            }
            string sign_str = total_row + rows.Aggregate((k, v) => k + "|" + v);
            total_row = total_row + RSAFromPkcs.sign2Hex(sign_str, _hfSign.hf_privateKey, "utf-8");
            StringBuilder sb = new StringBuilder();
            sb.Append(total_row);
            sb.AppendLine();
            foreach (var row in rows) {
                sb.Append(row);
                sb.AppendLine();
            }
            var fileName = IOHelper.GetMapPath("HF", DateTime.Now.ToString("yyyyMMdd"), batchFileName);
            //File.WriteAllText(fileName, sb.ToString(), Encoding.UTF8);
            UTF8Encoding utf8 = new UTF8Encoding(false);
            using (StreamWriter sw = new StreamWriter(fileName, false, utf8)) {
                sw.WriteLine(sb.ToString());
                sw.Close();
                sw.Dispose();
            }
            //商户申请批号写入库
            var batchId = _iTransferService.ApplyTransfer(model);
            //FTP上传
            try {
                var ftp = new FtpClient(_hfSign.ftp_ip, _hfSign.ftp_name, _hfSign.ftp_pwd);
                ftp.DataConnectionType = FtpDataConnectionType.PASV;
                ftp.Connect();
                ftp.SetWorkingDirectory("/req");
                ftp.UploadFile(fileName, batchFileName);
                ftp.Disconnect();
                //代付通知
                hfData.head.merNo = _hfSign.merNo;
                hfData.head.tranCode = "0001";
                hfData.body = new hf_transfer_notify { fileName = batchFileName, privateData = "" };
                hfData.head.signature = _hfSign.Sign(hfData);
                var hfResult = await _hfSign.PayGateway<body_base>(hfData);
                if (hfResult != null && hfResult.body.respCode.Substring(0, 1) == "0")
                    _iTransferService.UpdateBatch(batchId, hfData.head.tranId, TransferBatchStatus.Notify);
                return ApiResultToJson.Json("提交成功", new batch_transfer_result { batch_no = model.batch_no, status = 1 });
            } catch {
                return ApiResultToJson.Json<batch_transfer_result>("FTP上传失败，请到批处理再次报盘");
            }
        }

        /// <summary>
        /// 提交代付批处理报盘通知（平台后台用）
        /// </summary>
        /// <returns>The transfer.</returns>
        /// <param name="batchId">Batch Id.</param>
        public async Task<int> TransferNotify(long batchId, string batchFileName, long merchant_id) {
            var fileName = IOHelper.GetMapPath("HF", "20" + batchFileName.Substring(0, 6), batchFileName);
            try {
                var ftp = new FtpClient(_hfSign.ftp_ip, _hfSign.ftp_name, _hfSign.ftp_pwd);
                ftp.DataConnectionType = FtpDataConnectionType.PASV;
                ftp.Connect();
                ftp.SetWorkingDirectory("/req");
                ftp.UploadFile(fileName, batchFileName);
                ftp.Disconnect();
                var hfData = new HFBankData<head_base, hf_transfer_notify>();
                hfData.head.merNo = _hfSign.merNo;
                hfData.head.tranCode = "0001";
                hfData.body = new hf_transfer_notify { fileName = batchFileName, privateData = "" };
                hfData.head.signature = _hfSign.Sign(hfData);
                var hfResult = await _hfSign.PayGateway<body_base>(hfData);
                if (hfResult != null && hfResult.body.respCode.Substring(0, 1) == "0") {
                    var result = _iTransferService.UpdateBatch(batchId, hfData.head.tranId, TransferBatchStatus.Notify);
                    return result;
                }
            } catch {
                throw new ServerErrorException("FTP上传失败，重新提交");
            }
            return 0;
        }

        /// <summary>
        /// 提交代付批处理查询，返回回盘文件地址后，进行提现记录更新（平台后台用）
        /// </summary>
        /// <returns>The transfer.</returns>
        /// <param name="batchId">Batch Id.</param>
        /// <param name="noticeTranId">报盘通知交易流水号</param>
        public async Task<int> TransferBack(long batchId, string noticeTranId, long merchant_id) {
            var hfData = new HFBankData<head_base, object>();
            hfData.head.merNo = _hfSign.merNo;
            hfData.head.tranCode = "0009";
            hfData.body = new { noticeTranId };
            hfData.head.signature = _hfSign.Sign(hfData);
            var hfResult = await _hfSign.PayGateway<hf_transfer_back>(hfData);
            if (hfResult != null && hfResult.body.respCode.Substring(0, 1) == "0" && !string.IsNullOrEmpty(hfResult.body.hpdz)) {
                string backName = hfResult.body.hpdz;
                backName = backName.Replace("/res/", "");
                TransferBatchStatus status = TransferBatchStatus.Back;
                var localFile = IOHelper.GetMapPath("HF", "20" + backName.Substring(0, 6), backName);
                var ftp = new FtpClient(_hfSign.ftp_ip, _hfSign.ftp_name, _hfSign.ftp_pwd);
                ftp.DataConnectionType = FtpDataConnectionType.PASV;
                ftp.Connect();
                ftp.SetWorkingDirectory("/res");
                ftp.DownloadFile(localFile, hfResult.body.hpdz);
                ftp.Disconnect();
                var platform_transfers = new List<platform_transfer>();
                string text = "";
                UTF8Encoding utf8 = new UTF8Encoding(false);
                using (StreamReader sr = new StreamReader(localFile, utf8, false)) {
                    text = sr.ReadToEnd();
                    sr.Close();
                    sr.Dispose();
                }
                text = RSAFromPkcs.decryptData2Hex(text, _hfSign.hf_privateKey, "utf-8");
                var lines = text.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
                int i = 0;
                foreach (var row in lines) {
                    if (i == 0) { i++; continue; }
                    var rowData = row.Split('|');
                    string respCode = rowData[5].Substring(0, 1);
                    TransferStatus transferStatus = TransferStatus.None;
                    if (respCode == "0") {
                        transferStatus = TransferStatus.Finish;
                    } else if (respCode == "1") {
                        transferStatus = TransferStatus.UnConfirm;
                    } else {
                        transferStatus = TransferStatus.Fail;
                    }
                    platform_transfers.Add(new platform_transfer {
                        order_no = "", pay_time = rowData[3].ToDateTime(),
                        transaction_no = rowData[1], fail = rowData[6], status = transferStatus
                    });
                    i++;
                }

                status = TransferBatchStatus.Treat;
                var result = _iTransferService.Transfer(platform_transfers, batchId, status, backName);
                return result;
            }
            return 0;
        }

        /// <summary>
        /// 单笔代付查询
        /// </summary>
        /// <returns>The query.</returns>
        /// <param name="model">Model.</param>
        public async Task<transfer_result> TransferQuery(transfer_query model) {
            transfer_dto order = null;
            if (!string.IsNullOrEmpty(model.order_no)) order = _iTransferService.Get(model.merchant_no, model.order_no);
            else order = _iTransferService.GetByTran(model.transaction_no);
            DateTime pay_time = order.pay_info.pay_time.HasValue ? order.pay_info.pay_time.Value : order.apply_time;
            var transaction_no = order.pay_info.transaction_no;
            if (string.IsNullOrEmpty(transaction_no))
                return ApiResultToJson.Json<transfer_result>("提现进行中");
            var hfData = new HFBankData<head_base, hf_transfer_query>();
            hfData.head.merNo = _hfSign.merNo;
            hfData.head.tranCode = "1201";
            hfData.body = new hf_transfer_query { origTranId = transaction_no, origTranTime = pay_time.ToString("yyyyMMddHHmmss") };
            hfData.head.signature = _hfSign.Sign(hfData);
            var hfResult = await _hfSign.PayGateway<hf_transfer_reuslt>(hfData);
            if (hfResult != null) {
                int status = 0;//结算状态：1－到账成功，2－不确定，3－失败
                string msg = "";
                if (hfResult.body.respCode == "0000") {
                    if (hfResult.body.origTranState == "0") {
                        //代付成功
                        status = 1;
                        msg = "提现成功";
                        //只处理不确定的状态为成功，因为账在上代付已扣
                        if (order.status == TransferStatus.UnConfirm)
                            _iTransferService.TransferSuccess(new platform_transfer {
                                pay_time = pay_time, transaction_no = transaction_no, merchant_no = model.merchant_no,
                                order_no = order.order_no, status = TransferStatus.Finish
                            });
                    } else if (hfResult.body.origTranState == "1") {
                        //不确定
                        status = 2;
                        msg = "提现中";
                    } else {
                        //代付失败
                        status = 3;
                        msg = string.IsNullOrEmpty(order.fail) ? hfResult.body.origRespMsg : order.fail;
                    }
                } else if (hfResult.body.respCode == "1101" && order.status == TransferStatus.UnConfirm) {
                    //返回0000表示查询成功；返回1101表示查无此交易，如果代付交易发完后隔2分钟查仍是1101，可确认为原交易失败；
                    //其他都是查询失败，需要再次查询。可能有退汇的数据，详情参考退汇查询接口。
                    msg = !string.IsNullOrEmpty(hfResult.body.origRespMsg) ? hfResult.body.origRespMsg : "提现失败";
                    status = 2;
                } else {
                    //代付失败
                    status = 3;
                    msg = string.IsNullOrEmpty(order.fail) ? hfResult.body.respMsg : order.fail;
                }
                return ApiResultToJson.Json(msg, new transfer_result {
                    order_no = order.order_no, transaction_no = transaction_no,
                    pay_time = pay_time, status = status
                });
            }
            return ApiResultToJson.Json<transfer_result>("异常提现查询");
        }
        #endregion

        #region 代收,T+1转账
        /// <summary>
        /// 代收签约－会发短信
        /// </summary>
        /// <returns>The receive.</returns>
        /// <param name="model">Model.</param>
        public async Task<ApiResultMessage> InsteadReceive(verify_model model) {
            var merchant = _iMerchantService.Get(model.merchant_no);
            var setting = merchant.setting;
            var hfData = new HFBankData<head_base, instead_receive>();
            hfData.head.merNo = setting.hf_set.quick_mchid;
            hfData.head.tranCode = "1401";
            hfData.body = new instead_receive {
                acctName = model.account_name, acctNo = model.account_no, certNo = model.id_card,
                certType = "00", phones = model.mobile, cardCvn2 = model.cvv2, cardExpire = model.expire
            };
            hfData.head.signature = _hfSign.Sign(hfData);
            var hfResult = await _hfSign.PayGateway<body_base>(hfData);
            if (hfResult != null) {
                if (hfResult.body.respCode.Substring(0, 1) == "0") {
                    return new ApiResultMessage(hfData.head.tranCode);
                } else
                    return new ApiResultMessage(1001, hfResult.body.respMsg);
            }
            return new ApiResultMessage(1002, "短信发送异常");
        }

        /// <summary>
        /// 代收签约－提交短信验证码
        /// </summary>
        /// <returns>The receive.</returns>
        /// <param name="model">Model.</param>
        public async Task<ApiResultMessage> InsteadReceive(verify_model_sms model) {
            var merchant = _iMerchantService.Get(model.merchant_no);
            var setting = merchant.setting;
            var hfData = new HFBankData<head_base, object>();
            hfData.head.merNo = setting.hf_set.quick_mchid;
            hfData.head.tranCode = "1702";
            hfData.body = new { origTranId = model.orig_tran_id, messageCode = model.code };
            hfData.head.signature = _hfSign.Sign(hfData);
            var hfResult = await _hfSign.PayGateway<body_base>(hfData);
            if (hfResult != null) {
                if (hfResult.body.respCode.Substring(0, 1) == "0") {
                    return new ApiResultMessage("提交成功");
                } else
                    return new ApiResultMessage(1001, hfResult.body.respMsg);
            }
            return new ApiResultMessage(1002, "提交异常");
        }

        /// <summary>
        /// 单笔代收
        /// </summary>
        /// <returns>The transfer.</returns>
        /// <param name="model">Model.</param>
        public async Task<transfer_result> AgencyFund(apply_receive model) {
            var merchant = _iMerchantService.Get(model.merchant_no);
            var setting = merchant.setting;
            var hfData = new HFBankData<head_base, hf_receive>();
            var transaction_no = hfData.head.tranId;
            model.transaction_no = transaction_no;
            DateTime pay_time = DateTime.Now;
            hfData.head.merNo = setting.hf_set.quick_mchid;
            hfData.head.tranCode = "2301";
            hfData.body = new hf_receive {
                payAcctNo = model.account_no, payAcctName = model.account_name, payBankCode = "", payBankName = "",
                busiType = "1", rcvBusiType = "1", rcvAcctName = model.rcv_account_name, rcvAcctNo = model.rcv_account_no,
                rcvBankName = model.rcv_bank_name, rcvBankCode = DtoHelper.RandCode(12), remark = "转账",
                tranAmt = model.tran_amount
            };
            hfData.head.signature = _hfSign.Sign(hfData);
            var hfResult = await _hfSign.PayGateway<body_base>(hfData);
            if (hfResult != null) {
                //如果返回码是1开头是未知，需要发起查询接口查询最终结果；开头为0-成功；1-不确定；其他失败
                var respCode = hfResult.body.respCode.Substring(0, 1);
                int status = 0;//结算状态：1－到账成功，2－不确定，3－失败
                string msg = "";
                if (respCode == "0") {
                    //成功，生成账单和账
                    status = 1;
                    msg = "提现成功";
                } else if (respCode == "1") {
                    //不确定，不生成账单和账
                    status = 2;
                    msg = "提现中";
                } else {
                    //代付失败，不生成账单和账
                    status = 3;
                    msg = !string.IsNullOrEmpty(hfResult.body.respMsg) ? hfResult.body.respMsg : "支付失败";
                }
                _iChargeService.AddByQuickPay(model, status, msg);
                return ApiResultToJson.Json(msg, new transfer_result {
                    order_no = model.order_no, transaction_no = transaction_no,
                    pay_time = pay_time, status = status
                });
            }

            return ApiResultToJson.Json<transfer_result>("异常提现");
        }
        #endregion

        #region 商户进件
        /// <summary>
        /// 外接进件
        /// </summary>
        /// <returns>The register.</returns>
        /// <param name="dto">Dto.</param>
        /// <param name="opt">Opts.</param>
        public async Task<merchant_register_result> MerchantRegister(merchant_register_model dto, string opt) {
            var oemer = _iMerchantService.Get(dto.merchant_no);
            var model = new pay_add_merchant();
            SetMerchantInfo(model, dto);
            SetMerchantBankInfo(model, dto, opt);
            SetPayType(model, dto, dto.settle_type);
            model.mchId = _hfSign.t0_native_mchid;
            if (!string.IsNullOrEmpty(dto.reg_merchant_no))
                model.subMchId = dto.reg_merchant_no;
            else
                model.subMchId = "";
            if (dto.settle_type == "T0") {
                model.mchId = _hfSign.t0_native_mchid;
                model.sign = _hfSign.Sign(model, _hfSign.t0_native_key);
            } else {
                model.mchId = _hfSign.t1_native_mchid;
                model.sign = _hfSign.Sign(model, _hfSign.t1_native_key);
            }
            var resultApi = await _hfSign.PostNative<pay_add_merchant_result>(model);
            if (resultApi != null)
                if (resultApi.returnCode == "0") {
                    if (resultApi.resultCode == "0") {
                        dto.reg_merchant_no = resultApi.subMchId;
                        string merchant_no = _iMerchantService.MerchantChannelRegister(dto);
                        return ApiResultToJson.Json(new merchant_register_result { merchant_no = merchant_no });
                    } else {
                        return ApiResultToJson.Json<merchant_register_result>(resultApi.errCodeDes);
                    }
                } else
                    return ApiResultToJson.Json<merchant_register_result>(resultApi.returnMsg);
            else
                return ApiResultToJson.Json<merchant_register_result>("api进件失败");
        }

        /// <summary>
        /// 商户信息登记
        /// </summary>
        /// <param name="bind_id"></param>
        /// <returns></returns>
        public async Task<merchant_register_result> MerchantRegister(long bind_id, string settle_type, PayChannel channel = PayChannel.None) {
            var binder = _iMerchantService.Get(bind_id);
            var oemer = _iMerchantService.Get(binder.oem_id.Value);
            var model = new pay_add_merchant { businessLicenseType = "", businessLicense = "" };
            SetMerchantInfo(model, binder);
            SetMerchantBankInfo(model, binder, "A");
            SetPayType(model, binder, settle_type);
            if (settle_type == "T0") {
                model.mchId = _hfSign.t0_native_mchid;
                model.sign = _hfSign.Sign(model, _hfSign.t0_native_key);
            } else {
                model.mchId = _hfSign.t1_native_mchid;
                model.sign = _hfSign.Sign(model, _hfSign.t1_native_key);
            }
            var resultApi = await _hfSign.PostNative<pay_add_merchant_result>(model);
            if (resultApi != null) {
                if (resultApi.returnCode == "0") {
                    if (resultApi.resultCode == "0") {
                        var dto = binder.setting.auth_info.ToDtoObject<merchant_register_model>();
                        dto.pay_channel = PayChannel.HF;
                        dto.settle_type = settle_type;
                        dto.reg_merchant_no = resultApi.subMchId;
                        dto.bind_no = binder.merchant_no;
                        dto.merchant_no = oemer.merchant_no;
                        _iMerchantService.MerchantChannelRegister(dto);
                        return ApiResultToJson.Json(new merchant_register_result { merchant_no = resultApi.subMchId });
                    } else {
                        return ApiResultToJson.Json<merchant_register_result>(resultApi.errCodeDes);
                    }
                } else
                    return ApiResultToJson.Json<merchant_register_result>(resultApi.returnMsg);
            }
            return ApiResultToJson.Json<merchant_register_result>("信息登记异常");
        }

        /// <summary>
        /// 商户信息修改
        /// </summary>
        /// <param name="bind_id"></param>
        /// <returns></returns>
        public async Task<merchant_register_result> MerchantModify(long bind_id, string settle_type, PayChannel channel = PayChannel.None) {
            var binder = _iMerchantService.Get(bind_id);
            var oemer = _iMerchantService.Get(binder.oem_id.Value);
            var model = new pay_add_merchant { businessLicenseType = "", businessLicense = "" };
            SetMerchantInfo(model, binder);
            SetMerchantBankInfo(model, binder, "M");
            SetPayType(model, binder, settle_type);
            if (settle_type == "T0") {
                model.mchId = _hfSign.t0_native_mchid;
                model.subMchId = binder.setting.hf_set.t0_native_mchid;
                model.sign = _hfSign.Sign(model, _hfSign.t0_native_key);
            } else {
                model.mchId = _hfSign.t1_native_mchid;
                model.subMchId = binder.setting.hf_set.t1_native_mchid;
                model.sign = _hfSign.Sign(model, _hfSign.t1_native_key);
            }
            var resultApi = await _hfSign.PostNative<pay_add_merchant_result>(model);
            if (resultApi != null) {
                if (resultApi.returnCode == "0") {
                    if (resultApi.resultCode == "0") {
                        var dto = binder.setting.auth_info.ToDtoObject<merchant_register_model>();
                        dto.pay_channel = PayChannel.HF;
                        dto.settle_type = settle_type;
                        dto.reg_merchant_no = resultApi.subMchId;
                        dto.bind_no = binder.merchant_no;
                        dto.merchant_no = oemer.merchant_no;
                        _iMerchantService.MerchantChannelRegister(dto);
                        return ApiResultToJson.Json(new merchant_register_result { merchant_no = resultApi.subMchId });
                    } else
                        return ApiResultToJson.Json<merchant_register_result>(resultApi.errCodeDes);
                } else {
                    return ApiResultToJson.Json<merchant_register_result>(resultApi.returnMsg);
                }
            }
            return ApiResultToJson.Json<merchant_register_result>("信息登记异常");
        }

        /// <summary>
        /// 设置支付方式
        /// </summary>
        /// <param name="model"></param>
        /// <param name="binder"></param>
        private void SetPayType(pay_add_merchant model, merchant_dto binder, string settle_type) {
            var ignores = new List<string> { "UNIONPAY", "GATEWAY", "PAYOFF", "NATIVEOFF" };
            var dics = new Dictionary<string, string>();
            dics.Add("WXPAY_JS", "wxPub");
            dics.Add("WXPAY_APP", "wxApp");
            dics.Add("WXPAY_MICRO", "wxMicro");
            dics.Add("WXPAY_QR", "wxPubQR");
            dics.Add("ALIPAY_QR", "alipayQR");
            dics.Add("ALIPAY_JS", "alipayQR");
            dics.Add("ALIPAY_APP", "alipayApp");
            dics.Add("ALIPAY_MICRO", "alipayMicro");
            dics.Add("JDPAY_QR", "jdQR");
            dics.Add("UNIONPAY_QR", "unionpayQR");
            dics.Add("QQ_QR", "qqwalletQR");
            var payTypes = new List<pay_type_model>();
            var binder_payments = _iMerchantService.GetPayments(binder.id);
            var payment = binder_payments.FirstOrDefault(c => c.payment.channel == PayChannel.HF && c.payment.is_register);
            foreach (var sett in payment.settles) {
                string code = sett.code;
                if (ignores.Contains(code))
                    continue;
                var settle = payment.settles.FirstOrDefault(c => c.settle_type == settle_type && c.code == code);
                payTypes.Add(new pay_type_model {
                    payTypeCode = dics[code],
                    rateType = 1,
                    rate = settle.fee * 100,
                    rmk = payment.payment.name
                });
            }
            model.payTypes = payTypes.ToJson();
        }
        private void SetPayType(pay_add_merchant model, merchant_register_model dto, string settle_type) {
            var ignores = new List<string> { "UNIONPAY", "GATEWAY", "PAYOFF", "NATIVEOFF" };
            var dics = new Dictionary<string, string>();
            dics.Add("WXPAY_JS", "wxPub");
            dics.Add("WXPAY_APP", "wxApp");
            dics.Add("WXPAY_MICRO", "wxMicro");
            dics.Add("WXPAY_QR", "wxPubQR");
            dics.Add("ALIPAY_QR", "alipayQR");
            dics.Add("ALIPAY_JS", "alipayQR");
            dics.Add("ALIPAY_APP", "alipayApp");
            dics.Add("ALIPAY_MICRO", "alipayMicro");
            dics.Add("JDPAY_QR", "jdQR");
            dics.Add("UNIONPAY_QR", "unionpayQR");
            dics.Add("QQ_QR", "qqwalletQR");
            var payTypes = new List<pay_type_model>();
            var oemer = _iMerchantService.Get(dto.merchant_no);
            var oemer_payments = _iMerchantService.GetPayments(oemer.id);
            var payment = oemer_payments.FirstOrDefault(c => c.payment.channel == PayChannel.HF && c.payment.is_register);
            foreach (var sett in payment.settles) {
                string code = sett.code;
                if (ignores.Contains(code))
                    continue;
                var settle = payment.settles.FirstOrDefault(c => c.settle_type == settle_type && c.code == code);
                payTypes.Add(new pay_type_model {
                    payTypeCode = dics[code],
                    rateType = 1,
                    rate = settle.fee * 100
                });
            }
            model.payTypes = payTypes.ToJson();
        }
        /// <summary>
        /// 设置商户信息
        /// </summary>
        /// <param name="model"></param>
        /// <param name="user"></param>
        private void SetMerchantInfo(pay_add_merchant model, merchant_dto user) {
            var authinfo = user.setting.auth_info;
            //model.merchantName = authinfo.account_name;
            model.merchantOperationType = "2";
            model.merchantName = model.merchantShortName = string.IsNullOrEmpty(user.setting.shop_info.shop_name) ? authinfo.account_name + "的小店" : user.setting.shop_info.shop_name;
            model.opName = authinfo.account_name;
            model.opPhone = authinfo.mobile;
            model.proName = authinfo.province;
            model.cityName = authinfo.city;
            model.areaName = authinfo.area;
            model.legalPersonType = "LEGAL_PERSON";
            model.categoryWx = string.IsNullOrEmpty(user.setting.hf_set.category_wx) ? "158" : user.setting.hf_set.category_wx;
            model.categoryZfb = string.IsNullOrEmpty(user.setting.hf_set.category_zfb) ? "2015062600002758" : user.setting.hf_set.category_zfb;
            model.categoryJd = string.IsNullOrEmpty(user.setting.hf_set.category_jd) ? "011002" : user.setting.hf_set.category_jd;
            model.telephone = authinfo.mobile;
            model.customerTelephone = authinfo.mobile;
            model.certificateType = 1;
            model.certificateNo = authinfo.id_card;
        }
        private void SetMerchantInfo(pay_add_merchant model, merchant_register_model dto) {
            //model.merchantName = dto.account_name;
            model.merchantOperationType = "2";
            model.merchantName = model.merchantShortName = dto.account_name + "的小店";
            model.opName = dto.account_name;
            model.opPhone = dto.mobile;

            var regions = _iRegionService.GetRegionNames(dto.region_id).Split(' ');
            model.proName = regions[0];
            model.cityName = regions.Length > 1 ? regions[1] : regions[0];
            model.areaName = regions.Length > 2 ? regions[2] : "";

            model.legalPersonType = "LEGAL_PERSON";
            model.categoryWx = "158";
            model.categoryZfb = "2015062600002758";
            model.categoryJd = "011002";
            model.telephone = dto.mobile;
            model.customerTelephone = dto.mobile;
            model.certificateType = 1;
            model.certificateNo = dto.id_card;
        }
        /// <summary>
        /// 设置商户银行卡信息
        /// </summary>
        /// <param name="model"></param>
        /// <param name="user"></param>
        private void SetMerchantBankInfo(pay_add_merchant model, merchant_dto user, string op) {
            var authinfo = user.setting.auth_info;
            var banks = new Dictionary<string, string>();
            banks.Add("ABC", "9009");
            banks.Add("BCM", "9005");
            banks.Add("BOC", "9021");
            banks.Add("CCB", "9008");
            banks.Add("CEB", "9002");
            banks.Add("CGB", "9012");
            banks.Add("CIB", "9015");
            banks.Add("CITIC", "9001");
            banks.Add("CMB", "9004");
            banks.Add("CMBC", "9010");
            banks.Add("HXB", "9003");
            banks.Add("ICBC", "9040");
            banks.Add("PSBC", "9006");
            banks.Add("SPDB", "9020");
            banks.Add("PAB", "9013");
            model.tradeType = op == "A" ? "cs.merchant.register" : "cs.merchant.modify";
            model.accountType = 1;
            model.bankAccName = authinfo.account_name;
            model.bankCardNo = authinfo.account_no;
            model.bankName = authinfo.branch_name;
            model.bankType = banks[authinfo.bank_code];
        }
        private void SetMerchantBankInfo(pay_add_merchant model, merchant_register_model dto, string op) {
            var banks = new Dictionary<string, string>();
            banks.Add("ABC", "9009");
            banks.Add("BCM", "9005");
            banks.Add("BOC", "9021");
            banks.Add("CCB", "9008");
            banks.Add("CEB", "9002");
            banks.Add("CGB", "9012");
            banks.Add("CIB", "9015");
            banks.Add("CITIC", "9001");
            banks.Add("CMB", "9004");
            banks.Add("CMBC", "9010");
            banks.Add("HXB", "9003");
            banks.Add("ICBC", "9040");
            banks.Add("PSBC", "9006");
            banks.Add("SPDB", "9020");
            banks.Add("PAB", "9013");
            model.tradeType = op == "A" ? "cs.merchant.register" : "cs.merchant.modify";
            model.accountType = 1;
            model.bankAccName = dto.account_name;
            model.bankCardNo = dto.account_no;
            model.bankName = dto.branch_name;
            model.bankType = banks[dto.bank_code];
        }
        #endregion

        #region 对账
        /// <summary>
        /// 生成对账文件
        /// </summary>
        /// <returns>The to file.</returns>
        /// <param name="create_date">Create date.</param>
        public async Task<int> ItpToFile(DateTime create_date) {
            int result = 0;
            var date = create_date.ToString("yyyyMMdd");
            string fileFormat = ".1044." + date + ".rsp";
            var kjFile = "itp_kj" + fileFormat;
            var dfFile = "itp" + fileFormat;
            var kj_localFile = IOHelper.GetMapPath("HF", date, kjFile);
            var df_localFile = IOHelper.GetMapPath("HF", date, dfFile);
            try {
                var ftp = new FtpClient(_hfSign.ftp_ip, _hfSign.ftp_name, _hfSign.ftp_pwd);
                ftp.DataConnectionType = FtpDataConnectionType.PASV;
                ftp.Connect();
                ftp.SetWorkingDirectory("/res");
                ftp.DownloadFile(kj_localFile, kjFile);
                result = 1;
                ftp.DownloadFile(df_localFile, dfFile);
                result = 2;
                ftp.Disconnect();
            } catch { }
            if (result == 2) {
                result = _iProfitDayService.Insert(new profit_day_dto {
                    create_date = create_date, file = fileFormat, status = 1, pay_channel = PayChannel.HF
                });
            } else
                result = 0;
            return await Task.FromResult(result);
        }

        /// <summary>
        /// 对账文件处理
        /// </summary>
        /// <returns>The itp.</returns>
        /// <param name="id">Identifier.</param>
        public int DealItp(long id) {
            var model = _iProfitDayService.Get(id);
            var strfile = model.file.Split('.')[2];
            var localFile = IOHelper.GetMapPath("HF", strfile, "itp_kj" + model.file);
            string text = "";
            UTF8Encoding utf8 = new UTF8Encoding(false);
            //快捷
            using (StreamReader sr = new StreamReader(localFile, utf8, false)) {
                text = sr.ReadToEnd();
                sr.Close();
                sr.Dispose();
            }
            var lines = text.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            decimal pay_amount = 0;
            //总费率成本
            decimal fee_cost = 0;
            var kj_dic = new List<itp_model>();
            foreach (var row in lines) {
                var arrs = row.Split('|');
                var state = arrs[4];
                if (state == "4") {
                    var transaction_no = arrs[1];
                    var amt = decimal.Parse(arrs[3]) / 100;
                    pay_amount += amt;
                    var fee_amt = decimal.Parse(arrs[8]);
                    fee_cost += fee_amt;
                    kj_dic.Add(new itp_model { transaction_no = transaction_no, cost_fee_amt = fee_amt, tran_amount = amt });
                }
            }
            //T1代付
            localFile = IOHelper.GetMapPath("HF", strfile, "itp" + model.file);
            using (StreamReader sr = new StreamReader(localFile, utf8, false)) {
                text = sr.ReadToEnd();
                sr.Close();
                sr.Dispose();
            }
            lines = text.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            //代付总金额
            decimal off_amount = 0;
            //代付成本
            var df_dic = new Dictionary<string, decimal>();
            foreach (var row in lines) {
                var arrs = row.Split('|');
                var state = arrs[9];
                if (state == "0") {
                    var transaction_no = arrs[2];
                    var amt = decimal.Parse(arrs[8]) / 100;
                    off_amount += amt;
                    df_dic.Add(transaction_no, 0);
                }
            }
            model.pay_amount = pay_amount;
            model.off_amount = off_amount;
            model.fee_cost = fee_cost;
            model.status = 2;
            var result = _iBillService.ChargeAccount(kj_dic, df_dic, PayChannel.HF, "UNIONPAY", model);
            return result;
        }

        public Task<mall_result> MallPay(mall_model obj) {
            throw new NotImplementedException();
        }

        public Task<transfer_result> TokenTransfer(long id) {
            throw new NotImplementedException();
        }

        public Task<transfer_result> TokenTransferQuery(transfer_query model) {
            throw new NotImplementedException();
        }
        #endregion
    }
}